#include <linux/module.h>
#include <linux/init.h>

#include <linux/mm.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/workqueue.h>

#include <asm/current.h>
#include <asm/ptrace.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("chzhou");

struct work_struct my_work;

void work_handle(struct work_struct* arg)
{
    long data = atomic_long_read(&arg->data);

    dump_stack();

    printk("current: %s, pid: %d\n", current->comm, current->pid);
    ssleep(3);
    printk("after sleep, data = 0x%x\n", data);    
    printk("&my_work = 0x%x\n", (unsigned int)&my_work);    
}

irqreturn_t irq_handle(int irq, void *dev_id)
{
    schedule_work(&my_work);
    printk("[%s %d ] data = %d\n", __FUNCTION__, __LINE__, (int)dev_id);
    return 0;
}

int dev_init(void)
{
    int ret = 0;

    INIT_WORK(&my_work, work_handle);

    set_irq_type(IRQ_EINT8, IRQ_TYPE_EDGE_RISING);
    ret = request_irq(IRQ_EINT8, irq_handle, 0, "my irq", (void *)123);
    if (ret) {    
        printk("request irq failed.\n");
        return -EBUSY;
    }

    printk("[%s %d ]\n", __FUNCTION__, __LINE__);
    return 0;
}

void dev_exit(void)
{
    free_irq(IRQ_EINT8, (void *)123);
    printk("[%s %d ]\n", __FUNCTION__, __LINE__);
}

module_init(dev_init);
module_exit(dev_exit);

